<?php
class DatabaseService{
	//TODO: add logging + exceptions
	public function executeViewAllStatement($statement, $columns, $modelClassName){
		$rc = $statement->execute();
		if ( false===$rc ) {
                printf('execute failed: %s', htmlspecialchars($statement->error));
                die;
        }
		$rc = $statement->store_result();
		if ( false===$rc ) {
                printf('store_result failed: %s', htmlspecialchars($statement->error));
                die;
        }
		
		$data = array() ; // Array that accepts the data. 
		$params = array() ; // Parameter array passed to 'bind_result()' 
		foreach($columns as $col_name) 
		{ 
		  // Assign the fetched value to the variable '$data[$name]' 
		  $params[] =& $data[$col_name] ; 
		} 
		$resultSet = array();
		$res = call_user_func_array(array($statement, "bind_result"), $params) ; 
		if(! $res) { 
		  echo "bind_result() failed: " . $mysqli->error . "\n";  //TODO: error
		} 
		else { 
		  $res = $statement->fetch(); 
		  while($res) { 
			  //echo "<pre>" . htmlentities(print_r($data, true)) . "</pre>\n"; //TODO: debug
			  $reflect  = new ReflectionClass($modelClassName);
			  array_push($resultSet, $instance = $reflect->newInstanceArgs($data));
			  $res = $statement->fetch() ;
		  } 
		} 
		$statement->close() ; 
		return $resultSet;
	}
	
	public function save($statement, $paramTypes, $values){		
		array_unshift($values, $paramTypes);
		$rc = call_user_func_array(array($statement, "bind_param"), $this->makeValuesReferenced($values)) ; 
		if ( false===$rc ) {
            printf('bind_param failed: %s', htmlspecialchars($statement->error));
			die;
        }
		
		$rc = $statement->execute();
		if ( false===$rc ) {
			printf('execute failed: %s', htmlspecialchars($statement->error));
			die;
        }
		
		$statement->close() ; 
		return true;
	}
	
	public function delete($statement, $paramTypes, $values){		
		array_unshift($values, $paramTypes);
		$rc = call_user_func_array(array($statement, "bind_param"), $this->makeValuesReferenced($values)) ; 
		if ( false===$rc ) {
            printf('bind_param failed: %s', htmlspecialchars($statement->error));
			die;
        }
		
		$rc = $statement->execute();
		if ( false===$rc ) {
			printf('execute failed: %s', htmlspecialchars($statement->error));
			die;
        }
		
		$statement->close() ; 
		return true;
	}
	
	public function update($statement, $paramTypes, $values){		
		array_unshift($values, $paramTypes);
		$rc = call_user_func_array(array($statement, "bind_param"), $this->makeValuesReferenced($values)) ; 
		if ( false===$rc ) {
            printf('bind_param failed: %s', htmlspecialchars($statement->error));
			die;
        }
		
		$rc = $statement->execute();
		if ( false===$rc ) {
			printf('execute failed: %s', htmlspecialchars($statement->error));
			die;
        }
		
		$statement->close() ; 
		return true;
	}
	
	private function makeValuesReferenced($arr){
		$refs = array();
		foreach($arr as $key => $value)
			$refs[$key] = &$arr[$key];
		return $refs;
	}
}